#include "puts_gets.h"
#include "printSyslog.h"
int recvn(int sockfd, void *buf, long total){
        char *p = (char *)buf;
            long cursize = 0;
            while(cursize < total){
                        ssize_t sret = recv(sockfd,p+cursize,total-cursize,0);
                        if(sret == 0){
                    return 1;
                        }
                                cursize += sret;           
            }
                return 0;               
}


//用户在客户端输入 gets /usr1/file1(网盘的虚拟路径) /home/54th/netdisk/user1/file1(客户端的真实路径)
//cmd ->parameter1 就是网盘的虚拟路径(/usr1/file1)
//char *front = /home/54th/netdisk/ 与虚拟路径拼接得到真实路径 /home/54th/netdisk/usr1/file1
//从真实路径里获取服务端真实的文件名 文件大小 文件内容然后发送到客户端
//进行2次send 和一次sendfile
int server_gets(cmd_t *cmd,int netfd,const pathStack_t *ppathStack,char*pathbase){
    PRINT_LOG(NULL, 0, "gets");
   //服务端发送文件到客户端
    //文件名
    char * filename = cmd->parameter1;
    char realpath[256] = {0};
    strcat(realpath,pathbase);
    getCwd(ppathStack,realpath+strlen(pathbase));
    strcat(realpath,filename);
    printf("server file path :%s\n",realpath);
   //realpath 是服务端的真实地址
   int fd = open(realpath,O_RDWR);
   printf("fd:%d\n",fd);
   //从服务端开的的文件的文件描述符
   train_t train;
   train.flag = 1;
    train.length = strlen(filename);
     memcpy(train.data,filename,train.length);
    //组装小火车 文件名
  send(netfd,&train,sizeof(train.length)+train.length+sizeof(int),MSG_NOSIGNAL);
    //发送文件大小
    struct stat statbuf;
    fstat(fd,&statbuf);
     train.length = sizeof(off_t);
     memcpy(train.data,&statbuf.st_size,train.length);
     printf("filesize = %ld\n",statbuf.st_size);
     send(netfd,&train,sizeof(train.length)+train.length+sizeof(int),MSG_NOSIGNAL);
     printf("server has going to translate file to client!\n");
   
//收到客户端发来的断点续传请求火车
recvn(netfd,&train,sizeof(train.length)+train.length+sizeof(int));
off_t cursize = 0;
if(train.flag == 0){
    printf("file not exist!\n");
}
else if(train.flag == 1){
memcpy(&cursize,train.data,train.length);
printf("file has exist in server filesize =%ld\n",cursize);
}
 lseek(fd,cursize,0);
     //循环发送文件
 if(statbuf.st_size>=104857600){
      //若文件大于100M就建立映射传输
     printf("this is a bigfile , will use mmap to transfile!\n");
        char *p = (char *)mmap(NULL,statbuf.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
        ERROR_CHECK(p,MAP_FAILED,"mmap"); 
        while(1){
            //若传输完毕
            if(cursize >= statbuf.st_size){
             break;
            }
            if(statbuf.st_size - cursize > 1000){
                train.length = 1000;
            }
            else{
                train.length = statbuf.st_size - cursize;
            }
            send(netfd,&train.flag,sizeof(train.flag),MSG_NOSIGNAL);
            //发送小火车长度
            send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
            send(netfd,p+cursize,train.length,MSG_NOSIGNAL);
            //发送文件内容
          cursize += train.length;
          //改cursize长度
        }
      train.length = 0;
        send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
        //表示传完了,发送空火车
        munmap(p,statbuf.st_size);
        close(fd);
        printf("bigfile has been translated!\n");
        return 0;
    }

else{
     while(1){
         //读文件数据1000个字节到火车data
        ssize_t sret = read(fd,train.data,sizeof(train.data));
        //获得火车长度
        train.length = sret;
    ssize_t sret1 = send(netfd,&train,sizeof(train),MSG_NOSIGNAL);
        if(sret == 0 || sret1 == -1){
            break;
        }
        usleep(1000);
     }
     close(fd);
     printf("file has been tranlated to client");
     return 0;
}
}

//用户在客户端输入 puts /home/54th/user1/file1(客户端文件的真实路径) /user1/file1(网盘的虚拟路径)
//cmd ->parameter2 就是网盘的虚拟路径(/user1/file1)
//char *front = /home/54th/netdisk/ 与虚拟路径拼接得到真实路径 /home/54th/netdisk/usr1/file1
//新建char数组存放客户端发来的文件名,再在服务器真实路径下通过文件名新建文件
//接收文件大小建立映射 改变文件大小 然后接收客户端发来的文件
int server_puts(int netfd,const pathStack_t *ppathStack,char *pathbase){
    PRINT_LOG(NULL, 0, "pus");
    //服务端接收客户端传来的文件;
    char realpath[256] = {0};
    strcat(realpath,pathbase);
    getCwd(ppathStack,realpath+strlen(pathbase));
    
    //realpath 是服务端的真实地址
    train_t train;
    train.flag = 1;
    char filename[256] = {0};
    //先收发来的文件名
    recvn(netfd,&train.flag,sizeof(int));
    recvn(netfd,&train.length,sizeof(train.length));
    recvn(netfd,train.data,train.length);
    memcpy(filename,train.data,train.length);
    printf("filename :%s\n",filename);
    strcat(realpath,filename);
    printf("realpath：%s\n",realpath);
    //再收发来的文件总长度
    off_t filesize;
    recvn(netfd,&train.flag,sizeof(int));
    recvn(netfd,&train.length,sizeof(train.length));
    recvn(netfd,train.data,train.length);
    memcpy(&filesize,train.data,train.length);
    
    printf("filesize = %ld\n", filesize);
    printf("server is going to wait file...\n");
    //在服务端真实的本地路径创建文件,修改大小 建立映射
    int fd = open(realpath,O_CREAT|O_RDWR|O_TRUNC,0666);
 //接收文件
 off_t cursize = 0;
 off_t lastsize = 0;
 off_t slice = cursize %100000;
 while(1){
        //接收火车的flag
    recvn(netfd,&train.flag,sizeof(int));
        //接收文件长度
        recvn(netfd,&train.length,sizeof(train.length));
        if(train.length < 1000){
            printf("train length = %d\n",train.length);
        }
        if(train.length == 0 ){
            break;
        }
       cursize += train.length;
       recvn(netfd,&train.data,train.length);
       //接收文件数据
       write(fd,&train.data,train.length);
       if(cursize - lastsize >slice ){
           printf("%5.2lf%%\r", cursize*100.0/filesize);
           usleep(1000);
           fflush(stdout);
           lastsize = cursize;
       }

    }
    printf("100.00\n");
   printf("server has recved file from client!\n");
 
 close(fd);

}


    
